alarm chrono
Adjustable column position, thumb clusters
Checkout V1 of this keyboard.
With the first edition i validated that i like ortholinear layout, this enables me to offset the columns relative to each other, but i cannot settle on how much to offset it, therefore i got the idea to make it adjustable, I've not seen this done before.
The keyboard base will have GPIO + I²C pulled out on a connector, allowing any kind of expansion I'll make the following modules: trackpoint, mouse buttons, thumb clusters, rollers for vertical scrolling and volume.
The trackpoint module is a PS/2 device, see QMK documentation and Trackpoint pinout
To print legends, multi color on the same layer see this cool blog: Creating a Keyboard - docs.juliaebert.com
I ought to use a PCB for this, but that doesn't play nice with my rapid proto typing.
Testing if this method can be manufactured on my 3D printer, it's only 2 lines wide.
Apparently I'm not the first to think of adjustable columns, bummer see this ReSummit/Seismos GitHub repo And this nezumee/zebra GitHub repo
This article is more of a timeline of how it actually happened, by meerly appending, instead of going back, and changing stuff
Again, printed on its side for greater dimensional accuracy
Came across this really cool keyboard called Dygma Defy youtube.com - video dygma.com - Blog post they show their design iterations on thumb clusters they seem to align with what i envisioned, namely ergonomically shaped buttons, which is possible due to the 3D printing manufacturing. They've done lots
Ordered an MCP23017 I²C GPIO expander in DIP28 package format. To use on the left side of the keyboard.
This layout avoids having 2 unit wide buttons, which would interfere with the column sliding mechanism. Instead these buttons are moved to 2 thumb clusters. Which i I'm eager to try out.
Here's the pile of prototypes it took to get a satisfying and functional mechanism and keycaps.
Soldered up the first module. I used stranded wire due to metal fatigue. This methodology seems to be feasible. I'm going to add pin header connectors to connect it to the board, so it can be disconnected and the module removed. Spanning the top is gonna be a prototype board PCB with all the diodes, connectors for modules, DIP28 GPIO expander and the TRRS headphone jack.
Done printing and cleaning up all the modules for the left side.
Printed the bottom for the left side it unfortunately bent slightly when the modules were put in place, even tho i was patient letting it cool down after printing. I held it over the stove, and counter bend it. Then placed it on a flat surface. Which fixed the curve.
Planned out the circuit diagram for the left side of the keyboard, everything fit really nicely. I'm excited to make it a reality. The top features pin headers for each sliding module. Which has 6 pins, 1 for the column, and 5 for the rows. The rows are connected to the diodes, which bridge the gap to their respective colored bus bars on the bottom side. Which forms a natural ╲ ╲ ╲ ╲ ╲ pattern. The columns have busbars on the bottom left side. Both bus bar clusters are terminated in 2 flex cable connections, one for the GPIO expander chip, and one for a male pin header for testing and debugging, it's also pin compatible with my old keyboard, allowing me to do an agile partial goal, and get success feeling of trying it out, motivating me to keep working, and getting to test it before i add to many variables and unknowns, which could lead to multiple failure points, making me have to debug multiple possible error sources at the same time. There's 2 rows of connection points next to the debug connector, which is a fine place to extend the connection on to thumb cluster module, which differs because it has the diodes on the module as opposed to on the circuit board. It has 1 pin for the row, and the rest for the columns. Because it's wired up like it was a row at the bottom of the keyboard. Finally the headphone jack fits in the top right corner, pointing upwards, since there's already going to be the cables from the sliding modules looping that way.
Painted the circuit board, to indicate where the busbars on the bottom are routed. Wired up a test setup to test the first 4x4 buttons, and it works, yay ^-^
So up to this point, i had the intention of making this into a full hand wired keyboard. But I don't like how the wires at the top ended up looking, so I've chosen to cut my losses and use my prototype to decide how I want the offsets to be, and as a test bed to remove my last few unknowns, namely, thumb cluster and I/O expander chip. I should have cut more corners, to test the core concept, before spending time, on the niceties.
Using this tutorial:
makerhacks.com ─ Use the MCP23017 GPIO Port Expander to Add 16 IO Pins
i was able to make the MicroPython example work, but issues arise.
It keeps throwing the exception: [Errno 5] EIO
, furthermore i2c.scan()
is not consistent with what it returns.
All this is despite forgoing the breadboard, in favor of directly soldered connections :/
# https://blog.node5.net/Custom%20keyboard%20V2#mcp23017-micropython-code-snippet
# Based on: https://www.makerhacks.com/mcp23017#h-using-mcp23017-with-raspberry-pi-pico-and-micropython
import time
import machine
i2c = machine.I2C(1,
sda=machine.Pin(0),
scl=machine.Pin(1),
)
i2cdevices = i2c.scan()
print(i2cdevices)
time.sleep(0.50)
i = 0
while 1:
try:
i2c.writeto_mem(0x20, 0x00, b'\xFF')
i2c.writeto_mem(0x20, 0x01, b'\x00')
i2c.writeto_mem(0x20, 0x13, b'\x00')
while 1:
i2c.writeto_mem(0x20, 0x13, b'\xFF')
time.sleep(0.50)
i2c.writeto_mem(0x20, 0x13, b'\x00')
time.sleep(0.50)
except Exception as ex:
i += 1
print(i, ex)
github.com ─ dhylands / rshell Can be used to make it easier, to work with MicroPython
The issues persisted, and i decided to move from MicroPython to C++ using the
Adafruit library
And since the github.com ─ earlephilhower/arduino─pico functions
bool SetSDA
and bool SetSCL
didn't work to change I²C 0 pins,
i change to the default pins GP4
for SDA
and GP4
for SCL
denoted by the Raspberry PI Pico pinout.
Still the issues persisted, still working sporadically for a bit, and then stopped working.
I then tried using pull─up resistors with a value of 4.7KΩ
. Still didn't work consistently.
I then searched around, and came across this forum post:
forum.arduino.cc ─ Problems with MCP23017 ─ Solved
And i followed the wiring described therein. Namely, tie A0
, A1
and A2
to ground,
Reset
to 3.3v
using a 1KΩ
pull-up resistor, and finally tie SDA
and SCL
to 3.3v using a 1KΩ
pull-up resistor
(see the following ascii art diagram)
┌── U ──┐
[ LED Anode ] GPB0 ( 8 ) ┤1 28├ GPA7 ( 7 )
GPB1 ( 9 ) ┤2 27├ GPA6 ( 6 )
GPB2 ( 10 ) ┤3 26├ GPA5 ( 5 )
GPB3 ( 11 ) ┤4 25├ GPA4 ( 4 )
GPB4 ( 12 ) ┤5 24├ GPA3 ( 3 )
GPB5 ( 13 ) ┤6 23├ GPA2 ( 2 )
GPB6 ( 14 ) ┤7 22├ GPA1 ( 1 )
GPB7 ( 15 ) ┤8 21├ GPA0 ( 0 )
[ 3.3v ] VDD ┤9 20├ INTA
[ GND ] VSS ┤10 19├ INTB
NC ┤11 18├ RESET [ 1KΩ → 3.3v ]
[ GP5 & 1KΩ → 3.3v ] SCL ┤12 17├ A2 [ GND ]
[ GP4 & 1KΩ → 3.3v ] SDA ┤13 16├ A1 [ GND ]
NC ┤14 15├ A0 [ GND ]
└───────┘
( x ) = Adafruit library number for this pin
[ x ] = Microcontroller pin
// https://blog.node5.net/Custom%20keyboard%20V2#mcp23017-c-code-snippet
// Based on: https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/examples/mcp23xxx_blink/mcp23xxx_blink.ino
// Blinks an LED attached to a MCP23017 pin.
#include <Adafruit_MCP23X17.h>
#define LED_PIN 8 // MCP23XXX pin LED is attached to
Adafruit_MCP23X17 mcp;
void setup() {
Serial.begin(9600);
// while (!Serial); // Wait for Serial connection, enable for debug of early code
Serial.println("MCP23017 Blink Test!");
// Find ID, by attempting initialization sequentially
int i = 0;
while (!mcp.begin_I2C(i)) {
Serial.print("Error with ID:");
Serial.println(i);
i++;
delay(10);
}
Serial.print("Success with ID:");
Serial.println(i);
mcp.pinMode(LED_PIN, OUTPUT);
Serial.println("Looping...");
}
void loop() {
Serial.print("High, millis: ");
Serial.println(millis());
mcp.digitalWrite(LED_PIN, HIGH);
delay(250);
Serial.print("Low, millis: ");
Serial.println(millis());
mcp.digitalWrite(LED_PIN, LOW);
delay(250);
}
I've iterated on the thumb cluster design (based on the amazing work by the Dygma Defy team) and I've reached a design that works for me.
I've now moved to using 2 separate breadboards to test if the I²C is stable over the cable (it seems to be). Pulling the TRRS cable while powered, doesn't break it, but does require a power cycle to function again.
// https://blog.node5.net/Custom%20keyboard%20V2#mcp23017-button-code
// Based on: https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/examples/mcp23xxx_combo/mcp23xxx_combo.ino
#include <Adafruit_MCP23X17.h>
#define BLINK_FREQUENCY 1000 // Milliseconds
#define LED_PIN 8 // LED pin on MCP23017
#define BUTTON_PIN 7 // Button pin on MCP23017
Adafruit_MCP23X17 mcp;
int blink_frequency; // Milliseconds
void setup() {
Serial.begin(9600);
//while (!Serial);
Serial.println("MCP23017 Blink Test!");
int i = 0;
while (!mcp.begin_I2C(i)) {
Serial.print("Error with ID:");
Serial.println(i);
i++;
delay(10);
}
Serial.print("Success with ID:");
Serial.println(i);
mcp.pinMode(LED_PIN, OUTPUT);
mcp.pinMode(BUTTON_PIN, INPUT_PULLUP);
Serial.println("Looping...");
}
void loop() {
// What is an interupt?
if (!mcp.digitalRead(BUTTON_PIN)) {
// Button pushed, light LED
blink_frequency = BLINK_FREQUENCY / 20;
} else {
blink_frequency = BLINK_FREQUENCY; // Milliseconds
}
// Alternate state every blink_frequency milliseconds
bool state = (millis() % (blink_frequency * 2)) > blink_frequency;
Serial.print("State: ");
Serial.println(state);
mcp.digitalWrite(LED_PIN, state);
}
MCP23017 working principle has been tested. Now it's time to make it work with QMK. The following keyboards implement the MCP23017.
# List keyboards containing mcp23017 case insensitive
grep -I --color=always -rnie "mcp23017" | cut -d'/' -f2 | uniq
# List files containing mcp23017 case insensitive with the file extension .h or .c
grep -I --color=always -rnie "mcp23017" --include \*.h --include \*.c | cut -d':' -f1 | uniq
Based on this tutorial: How to Design Mechanical Keyboard PCBs with Kicad, Joe Scotto - youtube.com
I'm adding an indicator LED, it's an RGB LED, meaning I'll have to add a current limiting resistor per color, with a unique value for each. I then run into the issue that the forward voltage of the blue LED is higher than the supply voltage, which is about 3v. What will happen to an LED if the forward voltage (Vf) is greater than its supply voltage? - electronics.stackexchange.com